#include "precompiled.h"
#include "elemental.h"
using namespace std;
using namespace weo::engine::item;
using namespace weo::engine::character::shaman;

Elemental::Elemental()
{
    Casterdps::Init();
    m_Classnr = weo::engine::character::Character::isAllowed("Shaman");
    m_Basevalues.push_back(Attribute("Agility",59));
    m_Basevalues.push_back(Attribute("Intellect",103));
    m_Basevalues.push_back(Attribute("Strength",103));
    m_Basevalues.push_back(Attribute("Stamina",116));
    m_Basevalues.push_back(Attribute("Spirit",122));
    m_Basevalues.push_back(Attribute("CritSpellRating",2.2f*CritSpellRating));
    m_Basevalues.push_back(Attribute("CritSpellRating",5.0f*CritSpellRating));
    m_Basevalues.push_back(Attribute("Health",2979)); // health
    m_Basevalues.push_back(Attribute("Mana",2678)); // mana
    //	talents
    m_Basevalues.push_back(Attribute("CritSpellRating",6.0f*CritSpellRating));
    m_Basevalues.push_back(Attribute("HitSpellRating",9.0f*HitSpellRating));
    m_Equip.Mode(0);
    BOOST_FOREACH(Attribute attr, m_Basevalues)
    {
        handleAttribute(attr);
    }
    // base settings finished
    Buff *blindinglight = new Buff("Flask of Blinding Light");
    blindinglight->addAttribute(Attribute("ArcaneSpellDamage", 80));
    blindinglight->addAttribute(Attribute("HolySpellDamage", 80));
    blindinglight->addAttribute(Attribute("NatureSpellDamage", 80));
    m_Buffs[blindinglight->Name()] = *blindinglight;
    Buff *wshield = new Buff("Watershield");
    wshield->addAttribute(Attribute("MP5", (203*3)/60.0f * 5.0f));
    m_Buffs[wshield->Name()] = *wshield;
    m_Buffs["Totem of Wrath"].Active(true);
}
float Elemental::evaluateTF()
{
    float runtime = 600;
    float time = runtime ;
    float mana = m_Equip[35];
    float intellect = m_Equip[2];
    float spirit = m_Equip[5];
    float spelldmg = m_Equip[23] + m_Equip[27];
    float crit = m_Equip[12] / CritSpellRating;
    float hit = min<float>(83 + (m_Equip[11] / HitSpellRating), 99.0f);
    float haste = m_Equip[13] / HasteSpellRating;
    float mp5 = m_Equip[21] + 0.06f*intellect;
    if(m_Equip.hasSpecial(235117))
    {
        crit += 35.0f/CritSpellRating;
        mp5 += 15;
        spelldmg += 45;
        time -= (runtime/120)*4*1.5f; // totem time
        mp5 -= (665/120.0f)*5; // totem mana
    }
    if(m_Equip.hasSpecial(1337535))
    {
        spelldmg += 85;
    }
    float focusprob = (0.8f*(crit/100)-(pow(crit/100,2.0f)*0.4f))*1.1f; // 1.1f is for lo
    float lb12ctime = max<float>(2.0f/(1+haste/100),1.5f);
    if(m_Equip.hasSpecial(1254409))
    {
        spelldmg += min<float>(1.0f,(30.0f/lb12ctime)*(crit/100)*0.2f) * (190.0f/4.0f);
    }
    float lb12mana = max<float>(300*0.9f*(1-focusprob) - (mp5/5)*lb12ctime,1);
    float lb12dmg = 603;
    float lb12mult = 1.05f;
    float manaregooc = mp5/5 + (spirit/ 5 + 15) / 2.0f;
    float count = mana / lb12mana;
    float castuseratio = (manaregooc * lb12ctime) / lb12mana;
    time -= count * lb12ctime + max<float>(5 * castuseratio, 5);
    time = max<float>(time, 0);
    if(time > 0)
    {
        float regtime = time / (castuseratio + 1);
        time -= regtime;
    }
    count += time / lb12ctime;
    count = min<float>(count, runtime / lb12ctime);
    float lofactor = 1 + (0.2f*0.5f);
    float lbcritmult = 1.0f;
    if(m_Equip.hasSpecial(445202)) // chaos metagem
    {
        lbcritmult *= 1.03f;
    }
    if(m_Equip.hasSpecial(837862))
    {
        lbcritmult *=1.05f;
    }
    float fulldmg = (1 + crit / 100) * (hit/100) * lofactor * lbcritmult * lb12mult * (lb12dmg + 0.794f * spelldmg) * count;
    return m_CondFactor * fulldmg / runtime;
}
void Elemental::filterEquip(std::vector<std::vector<const weo::engine::item::Item*>>& items)
{
    for(unsigned int i = 0;i<10;i++)
    {
        int subtype = 3;
        if(i == 1 || i == 3)
        {
            vector<const Item*> temp = m_Database->getPtrbyType(1,i+1);
            items.push_back(temp);
        }
        else
        {
            vector<const Item*> temp = m_Database->getPtrbyType(1,i+1,3); // mail		
            items.push_back(temp);
        }
    }
    items.push_back(m_Database->getPtrbyType(2,0));
    items.push_back(m_Database->getPtrbyType(2,0));
    items.push_back(m_Database->getPtrbyType(3,0));
    items.push_back(m_Database->getPtrbyType(3,0));
    // main hand weapons
    vector<const Item*> mainhand;
    for(int j = 1;j<3;j++)
    {
        vector<const Item*> weapon = m_Database->getPtrbyType(4,j,2);
        vector<const Item*>::iterator it;
        for(it=weapon.begin();it!=weapon.end();it++)
        {
            mainhand.push_back(*it);
        }
    }
    for(int j = 1;j<3;j++)
    {
        vector<const Item*> weapon = m_Database->getPtrbyType(4,j,5);
        vector<const Item*>::iterator it;
        for(it=weapon.begin();it!=weapon.end();it++)
        {
            mainhand.push_back(*it);
        }
    }
    // staff
    vector<const Item*> staff = m_Database->getPtrbyType(4,4,6);
    vector<const Item*>::iterator it;
    for(it=staff.begin();it!=staff.end();it++)
    {
        mainhand.push_back(*it);
    }
    // off hand weapons
    vector<const Item*> offhand;
    vector<const Item*> shield = m_Database->getPtrbyType(1,11);
    vector<const Item*> ohand = m_Database->getPtrbyType(1,12);
    for(it=shield.begin();it!=shield.end();it++)
    {
        offhand.push_back(*it);
    }
    for(it=ohand.begin();it!=ohand.end();it++)
    {
        offhand.push_back(*it);
    }
    items.push_back(mainhand);
    items.push_back(offhand);
    items.push_back(m_Database->getPtrbyType(4,5,15)); // totems
    items.push_back(m_Database->getPtrbyType(5,0));
    Casterdps::filterEquip(items);
}
void Elemental::handleAttribute(const Attribute& attr)
{
    switch(attr.Type())
    {	
    default:
        Casterdps::handleAttribute(attr);
        break;
    }
}
